package com.boilermaker.springaoplearning.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect // 标识这是一个切面类
@Component // 需要将该类交给 Spring 管理
@Slf4j
public class AspectDemo1 {

    @Pointcut("execution(* com.boilermaker.springaoplearning.controller.*.*(..))")
    public void controllerPointcut() {
    }

    // Around 环绕通知，表示通知可以在方法执行前，也可以在方法执行后
    @Around("controllerPointcut()")
    public Object recordTime(ProceedingJoinPoint pjp) {
        // 前置通知（打印时间戳）
        log.info("目标方法执行前...");
        long begin = System.currentTimeMillis();

        // 使用 Object 接收原始方法
        Object result;
        try {
            result = pjp.proceed(); // 执行原始方法
        } catch (Throwable e) {
            log.info("目标方法抛出异常..."); // 异常后通知
            throw new RuntimeException(e);
        }

        // 后置通知（打印时间戳，计算耗时）
        log.info("目标方法执行后...");
        long end = System.currentTimeMillis();
        log.info(pjp.getSignature() + " 执行耗时：" + (end - begin) + " ms");

        return result;
    }
}

//    @Before("execution(* com.boilermaker.springaoplearning.controller.*.*(..))")
//    public void doBefore() {
//        log.info("前置通知...");
//    }
//
//    @After("execution(* com.boilermaker.springaoplearning.controller.*.*(..))")
//    public void doAfter() {
//        log.info("后置通知...");
//    }
//
//    @AfterReturning("execution(* com.boilermaker.springaoplearning.controller.*.*(..))")
//    public void doAfterReturning() {
//        log.info("返回后通知...");
//    }
//
//    @AfterThrowing("execution(* com.boilermaker.springaoplearning.controller.*.*(..))")
//    public void doAfterThrowing() {
//        log.info("异常后通知...");
//    }
